<%
'######################################################################
'## ab.http.asp
'## -------------------------------------------------------------------
'## Feature     :   AspBox XMLHTTP Class
'## Version     :   v1.0
'## Author      :   Lajox(lajox@19www.com)
'## Update Date :   2013/02/17 22:12
'## Description :   Request XMLHttp Data in AspBox
'## http://msdn.microsoft.com/en-us/library/ms535874(VS.85).aspx
'######################################################################

Class Cls_AB_Http
	Public Url, Method, CharSet, Async, User, Password, Html, Headers, Body, Text, SaveRandom
	Public ResolveTimeout, ConnectTimeout, SendTimeout, ReceiveTimeout
	Private s_data, s_url, s_ohtml, o_rh', a_rh()

	Private Sub Class_Initialize
		CharSet = AB.CharSet
		Async = False
		User = ""
		Password = ""
		s_data = ""
		s_url = ""
		Html = ""
		Headers = ""
		Body = Empty
		Text = Empty
		SaveRandom = True
		ResolveTimeout = 20000
		ConnectTimeout = 20000
		SendTimeout = 300000
		ReceiveTimeout = 60000
		AB.Error(46) = "远程服务器没有响应"
		AB.Error(47) = "服务器不支持XMLHTTP组件"
		AB.Error(48) = "要获取的页面地址不能为空"
		AB.Use "List"
		Set o_rh = AB.List.New
	End Sub

	Private Sub Class_Terminate
		Set o_rh = Nothing
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Http.New 方法
	'# @syntax: Set http = AB.Http.New
	'# @return: Object (ASP对象)
	'# @dowhat: 创建Http核心对象, 创建一个 AspBox_Http 对象
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# Dim http : Set http = AB.Http.New 	'创建Http核心对象
	'------------------------------------------------------------------------------------------

	Public Function [New]()
		Set [New] = New Cls_AB_Http
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Url 属性
	'# @syntax: AB.Http.Url[ = string]
	'# @return: String (字符串) 返回要获取数据的远程URL地址
	'# @dowhat: 设置要获取的远程文件地址，此属性可读可写
	'#  此属性可以设置要获取的远程文件地址，只在用 AB.Http.Open 方法获取数据时有效。
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# none
	'------------------------------------------------------------------------------------------

	'------------------------------------------------------------------------------------------
	'# AB.Http.Method 属性
	'# @syntax: AB.Http.Method[ = string]
	'# @return: String (字符串) 当前采用的数据请求方式
	'# @dowhat: 设置获取远程文件数据时请求数据的方式，此方法可读可写
	'#  通过此属性可以设置获取远程文件时数据请求的方式，通常是 "GET" 或者 "POST" 方式。此属性默认为 "GET"。
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# none
	'------------------------------------------------------------------------------------------

	'------------------------------------------------------------------------------------------
	'# AB.Http.CharSet 属性
	'# @syntax: AB.Http.CharSet = charset
	'# @return: String (字符串) 返回设置的远程文件的编码
	'# @dowhat: 指定远程文件的编码，此属性可读可写
	'#  指定的是远程文件的编码，并非本地文件所使用的编码，若编码设置不正确，取到的远程文件有可能是乱码或空白。
	'#  可用值为"UTF-8"或"GB2312"等。默认为 AB.CharSet 的值。
	'--DESC------------------------------------------------------------------------------------
	'# @param: charset String (字符串)
	'# 代表字符集编码的字符串，如：
	'# "BIG5" - 繁体中文
	'# "GB2312" - 简体中文
	'# "KOI8-R" - 俄语
	'# "UTF-8" - ASCII兼容的多字节8编码
	'# 默认为 AB.CharSet 的值。
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# AB.Http.CharSet = "UTF-8"
	'------------------------------------------------------------------------------------------

	'------------------------------------------------------------------------------------------
	'# AB.Http.Data 属性(只写)
	'# @syntax: AB.Http.Data = data
	'# @return: 无返回值
	'# @dowhat: 在获取远程文件时要同时提交的数据，只属性只写
	'#  如果在使用GET或者POST方式获取远程数据时，可以通过此属性同时提交数据。
	'#  GET会以URL参数的方式附加这些数据，POST则会类似表单一样提交这些数据。
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim url : url = "http://so.zhulang.com/search.php"
	'# 'h.SetHeader "referer:www.zhulang.com"
	'# 'h.SetHeader "content-type:application/x-www-form-urlencoded"
	'# h.Method = "POST"
	'# 'h.Async = False
	'# Dim key : key = "少年"
	'# 'AB.Use "E" : key = AB.E.escape(key) '远程为asp,一般用escape
	'# AB.Use "E" : key = AB.E.encodeURIComponent(key) '远程为php,一般用encodeURIComponent
	'# h.Data = "t=zh&k=" & key
	'# h.Charset = "UTF-8"
	'# Dim str : str = h.Post(url)
	'# Set h = Nothing
	'# AB.C.Print str
	'------------------------------------------------------------------------------------------

	Public Property Let Data(ByVal s)
		s_data = s
	End Property

	Public Sub SetHeader(ByVal a)
		Dim i,n,v
		If isArray(a) Then
			For i = 0 To Ubound(a)
				n = LCase(Replace(Trim(AB.C.Cleft(a(i),":")),"-","_"))
				v = AB.C.CRight(a(i),":")
				o_rh(n) = v
			Next
		Else
			n = LCase(Replace(Trim(AB.C.Cleft(a,":")),"-","_"))
			v = AB.C.CRight(a,":")
			o_rh(n) = v
		End If
	End Sub

	Public Property Let RequestHeader(ByVal n, ByVal v)
		n = Replace(n,"-","_")
		o_rh(n) = v
	End Property

	Public Property Get RequestHeader(ByVal n)
		If AB.C.Has(n) Then
			RequestHeader = o_rh(n)
		Else
			RequestHeader = Join(o_rh.Hash,vbCrLf)
		End If
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.Http.Open 方法
	'# @syntax: AB.Http.Open
	'# @return: String (字符串) 返回目标远程地址的源代码字符串
	'# @dowhat: 用属性配置方式获取远程文件数据
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.url = "http://www.baidu.com/index.php"
	'# 'h.method = "GET"
	'# 'h.async = False
	'# 'h.charset = AB.CharSet
	'# 'h.data = ""
	'# 'h.user = "" : h.password = ""
	'# Dim str : str = h.Open
	'# Set h = Nothing
	'# AB.C.Print str
	'------------------------------------------------------------------------------------------

	Public Function [Open]
		[Open] = GetData(Url, Method, Async, s_data, User, Password)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Get 方法
	'# @syntax: AB.Http.Get url
	'# @return: String (字符串) 返回目标远程地址的源代码字符串
	'# @dowhat: 用GET方式请求远程文件的数据
	'--DESC------------------------------------------------------------------------------------
	'# @param url: [String] (字符串) 目标远程地址
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim str : str = h.Get("http://www.baidu.com/index.php")
	'# Set h = Nothing
	'# AB.C.Print str
	'------------------------------------------------------------------------------------------

	Public Function [Get](ByVal uri)
		[Get] = GetData(uri, "GET", Async, s_data, User, Password)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Post 方法
	'# @syntax: AB.Http.Post url
	'# @return: String (字符串) 返回目标远程地址的源代码字符串
	'# @dowhat: 用POST方式请求远程文件的数据
	'--DESC------------------------------------------------------------------------------------
	'# @param url: [String] (字符串) 目标远程地址
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim str : str = h.Post("https://passport.baidu.com/?login")
	'# Set h = Nothing
	'# AB.C.Print str
	'------------------------------------------------------------------------------------------

	Public Function Post(ByVal uri)
		Post = GetData(uri, "POST", Async, s_data, User, Password)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.GetData 方法
	'# @syntax: AB.Http.GetData url, method, async, data, user, password
	'# @return: String (字符串) 返回目标远程地址的源代码字符串
	'# @dowhat: 用参数配置的方式获取远程文件数据
	'--DESC------------------------------------------------------------------------------------
	'# @param url: [String] (字符串) 目标远程地址
	'# @param method: [String] (字符串) 数据请求方式（GET 或 POST）默认为GET
	'# @param async: [Boolean] (布尔值) 指定此请求是否为异步方式（True / False）默认为False
	'# @param data: [String] (字符串) 针对POST方法发送的数据, 默认为空
	'# @param user: [String] (字符串)
	'#  如果服务器需要验证，此处指定用户名，如果未指定，当服务器需要验证时，会弹出验证窗口, 默认为空
	'# @param password: [String] (字符串) 验证信息中的密码部分，如果用户名为空，则此值将被忽略, 默认为空
	'--DEMO------------------------------------------------------------------------------------
	'# '-------GET获取源代码---------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim url : url = "http://www.baidu.com/index.php"
	'# 'h.SetHeader "referer:www.baidu.com"
	'# 'h.SetHeader "content-type:application/x-www-form-urlencoded"
	'# Dim method : method = "GET"
	'# Dim async : async = False
	'# Dim data : data = ""
	'# Dim user : user = ""
	'# Dim password : password = ""
	'# Dim charset : charset = AB.CharSet : h.charset = charset
	'# Dim str : str = h.GetData(url, method, async, data, user, password)
	'# 'str = h.GetData(url, "", "", "", "", "")
	'# Set h = Nothing
	'# AB.C.Print str
	'# '-------asp模拟POST提交---------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim url : url = "http://www.ip138.com/ips1388.asp"
	'# h.SetHeader "content-type:application/x-www-form-urlencoded"
	'# h.SetHeader "referer:www.ip138.com"
	'# Dim method : method = "POST"
	'# Dim async : async = False
	'# Dim data : data = "ip=14.1.20.91&action=2"
	'# Dim user : user = ""
	'# Dim password : password = ""
	'# Dim charset : charset = AB.CharSet : h.charset = charset
	'# Dim str : str = h.GetData(url, method, async, data, user, password)
	'# Set h = Nothing
	'# AB.C.Print str
	'------------------------------------------------------------------------------------------

	Public Function GetData(ByVal uri, ByVal m, ByVal async, ByVal data, ByVal u, ByVal p)
		Dim o,chru
		'Set o = CreateHTTPPoster(1)
		If AB.C.isInstall("MSXML2.serverXMLHTTP") Then
			Set o = Server.CreateObject("MSXML2.serverXMLHTTP")
		ElseIf AB.C.isInstall("MSXML2.XMLHTTP") Then
			Set o = Server.CreateObject("MSXML2.XMLHTTP")
		ElseIf AB.C.isInstall("Microsoft.XMLHTTP") Then
			Set o = Server.CreateObject("Microsoft.XMLHTTP")
		Else
			AB.Error.Raise 47
			Exit Function
		End If
		o.SetTimeOuts ResolveTimeout, ConnectTimeout, SendTimeout, ReceiveTimeout
		If AB.C.IsNul(uri) Then AB.Error.Raise 48 : Exit Function
		If AB.C.Test(uri,"^[\w\d-]+>https?://") Then
			CharSet = AB.C.Cleft(uri,">")
			uri = AB.C.CRight(uri,">")
		End If
		s_url = uri
		m = AB.C.IIF(AB.C.Has(m),UCase(m),"GET")
		If AB.C.IsNul(async) Then async = False
		If m = "GET" And AB.C.Has(data) Then uri = uri & AB.C.IIF(Instr(uri,"?")>0, "&", "?") & Serialize__(data)
		If AB.C.Has(u) Then
			o.open m, uri, async, u, p
		Else
			o.open m, uri, async
		End If
		If m = "POST" Then
			If Not o_rh.HasIndex("content_type") Then
				o_rh("content_type") = "application/x-www-form-urlencoded"
			End If
			SetHeaderTo o
			o.send Serialize__(data)
		Else
			SetHeaderTo o
			o.send
		End If
		If o.readyState <> 4 Then
			GetData = "error:server is down"
			Set o = Nothing
			AB.Error.Raise 46
			Exit Function
		ElseIf o.Status = 200 Then
			Headers = o.getAllResponseHeaders()
			Body = o.responseBody
			Text = o.responseText
			If AB.C.IsNul(CharSet) Then
				If AB.C.Test(Headers,"charset=([\w-]+)") Then
					CharSet = AB.C.RegReplace(Headers,"([\s\S]+)charset=([\w-]+)([\s\S]+)","$2")
				ElseIf AB.C.Test(Headers,"Content-Type: ?text/xml") Then
					CharSet = AB.C.RegReplace(Text,"^<\?xml\s+[^>]+encoding\s*=\s*""([^""]+)""[^>]*\?>([\s\S]+)","$1")
				ElseIf AB.C.Test(Text,"<meta\s+http-equiv\s*=\s*[""']?content-type[""']?\s+content\s*=\s*[""']?[^>]+charset\s*=\s*([\w-]+)[^>]*>") Then
					CharSet = AB.C.RegReplace(Text,"([\s\S]+)<meta\s+http-equiv\s*=\s*[""']?content-type[""']?\s+content\s*=\s*[""']?[^>]+charset\s*=\s*([\w-]+)[^>]*>([\s\S]+)","$2")
				End If
				If AB.C.IsNul(CharSet) Then CharSet = AB.CharSet
			End If
			GetData = Bytes2Bstr__(Body, CharSet)
		Else
			GetData = "error:" & o.Status & " " & o.StatusText
		End If
		Set o = Nothing
		s_ohtml = GetData
		Html = s_ohtml
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.CreateHTTPPoster 方法
	'# @syntax: [Set obj =] AB.Http.CreateHTTPPoster(soc)
	'# @return: Object (ASP对象) 原始 XMLHTTP对象
	'# @dowhat: 创建一个尽可能高版本的XMLHTTP
	'--DESC------------------------------------------------------------------------------------
	'# @param soc: [Integer] (整型) 是否为 ServerXMLHTTP 还是 XMLHTTP 的对象
	'--DEMO------------------------------------------------------------------------------------
	'# Dim XmlHttp : Set XmlHttp = AB.Http.CreateHTTPPoster(0)
	'------------------------------------------------------------------------------------------

	Public Function CreateHTTPPoster(soc)
		Dim s
		If soc = 1 Then : s = "ServerXMLHTTP" : Else : s = "XMLHTTP" : End If
		On Error Resume Next
		Set CreateHTTPPoster = Server.CreateObject("MSXML2." & s & ".4.0")
		If Err.Number<>0 Then
			Err.Clear
			Set CreateHTTPPoster = Server.CreateObject("MSXML2." & s & ".3.0")
			If Err.Number<>0 Then
				Err.Clear
				Set CreateHTTPPoster = Server.CreateObject("MSXML2." & s)
				If Err.Number<>0 Then
					Set CreateHTTPPoster = Nothing
				Else
					Exit Function
				End If
			Else
				Exit Function
			End If
		Else
			Exit Function
		End If
		On Error GoTo 0
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Find 方法
	'# @syntax: AB.Http.Find regex
	'# @return: String (字符串) 返回匹配正则表达式的字符串
	'# @dowhat: 在结果中查找首个匹配正则表达式的字符串
	'#  调用此方法可以返回读取的远程文件的结果中匹配参数中的正则表达式的字符串，
	'#  如果有多个结果符合匹配，则返回第1个匹配的结果。
	'--DESC------------------------------------------------------------------------------------
	'# @param regex: [String] (字符串) 正则表达式
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.Get("http://www.baidu.com/index.php")
	'# Dim str : str = h.Find("<img[\s]+src=""[^""]*""[^>]*>")
	'# Set h = Nothing
	'# AB.C.Print str
	'上面返回结果如：<img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129">
	'------------------------------------------------------------------------------------------

	Public Function Find(ByVal rule)
		Find = Find_(s_ohtml, rule)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Find_ 方法
	'# @syntax: AB.Http.Find_ string, regex
	'# @return: String (字符串) 返回在结果字符串中匹配正则表达式的字符串
	'# @dowhat: 在结果字符串中查找首个匹配正则表达式的字符串
	'#  调用此方法可以在指定的结果字符串中匹配参数中的正则表达式的字符串，
	'#  如果结果字符串中有多个符合匹配，则返回第1个匹配的结果。
	'--DESC------------------------------------------------------------------------------------
	'# @param string: [String] (字符串) 指定的结果字符串
	'# @param regex: [String] (字符串) 正则表达式
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim s : s = h.Get("http://www.baidu.com/index.php")
	'# Dim str : str = h.Find_(s, "<img[\s]+src=""[^""]*""[^>]*>")
	'# Set h = Nothing
	'# AB.C.Print str
	'上面返回结果如：<img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129">
	'------------------------------------------------------------------------------------------

	Public Function Find_(ByVal s, ByVal rule)
		If AB.C.Test(s,rule) Then Find_ = AB.C.RegReplace(s,"([\s\S]*?)("&rule&")([\s\S]*)","$2")
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Select 方法
	'# @syntax: AB.Http.Select regex, result
	'# @return: String (字符串) 读取的远程文件的结果代码中经过选择和替换的文本
	'# @dowhat: 在读取的远程文件的结果代码中按正则编组选择和替换匹配的文本
	'#  调用此方法可以按参数 regex 中的正则表达式选择匹配的字符串，
	'#  并在参数 result 中的用$N编组符号引用匹配的结果，返回经过选择的字符串。
	'--DESC------------------------------------------------------------------------------------
	'# @param regex: [String] (字符串) 正则表达式
	'# @param result: [String] (字符串) 可用$N编组符号引用匹配的结果
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.Get("http://www.baidu.com/index.php")
	'# Dim str : str = h.Select("<img[\s]+src=""([^""]*)""[^>]*>", "$1")
	'# Set h = Nothing
	'# AB.C.Print str
	'上面返回结果如：http://www.baidu.com/img/baidu_sylogo1.gif
	'------------------------------------------------------------------------------------------

	Public Function [Select](ByVal rule, ByVal part)
		[Select] = Select_(s_ohtml, rule, part)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Select_ 方法
	'# @syntax: AB.Http.Select_ string, regex, result
	'# @return: String (字符串) 指定的结果字符串经过选择和替换的文本
	'# @dowhat: 在指定的结果字符串中按正则编组选择和替换匹配的文本
	'#  调用此方法可以按参数 regex 中的正则表达式选择匹配的字符串，
	'#  并在参数 result 中的用$N编组符号引用匹配的结果，返回经过选择的字符串。
	'--DESC------------------------------------------------------------------------------------
	'# @param string: [String] (字符串) 指定的结果字符串
	'# @param regex: [String] (字符串) 正则表达式
	'# @param result: [String] (字符串) 可用$N编组符号引用匹配的结果
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim s : s = h.Get("http://www.baidu.com/index.php")
	'# Dim str : str = h.Select_(s, "<img[\s]+src=""([^""]*)""[^>]*>", "$1")
	'# Set h = Nothing
	'# AB.C.Print str
	'上面返回结果如：http://www.baidu.com/img/baidu_sylogo1.gif
	'------------------------------------------------------------------------------------------

	Public Function Select_(ByVal s, ByVal rule, ByVal part)
		If AB.C.Test(s,rule) Then
			part = Replace(part,"$0",Find_(s,rule))
			Select_ = AB.C.RegReplace(s,"(?:[\s\S]*?)(?:"&rule&")(?:[\s\S]*)",part)
		End If
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Search 方法
	'# @syntax: AB.Http.Search regex
	'# @return: Array (数组) 返回包含搜索结果字符串的数组
	'# @dowhat: 在读取的远程文件的结果代码中按正则表达式取得循环部分字符串并存进数组中
	'#  调用此方法可以把读取的远程文件的结果代码按正则表达式进行匹配，
	'#  把匹配到的一个或多个结果放到数组中并返回这个数组。
	'--DESC------------------------------------------------------------------------------------
	'# @param regex: [String] (字符串) 正则表达式
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.Get("http://www.baidu.com/index.php")
	'# Dim arr : arr = h.Search("<img[\s]+src=""[^""]*""[^>]*>")
	'# Set h = Nothing
	'# AB.Trace arr
	'上面返回结果如：
	'arr(0) = "<img src=""http://www.baidu.com/img/baidu_sylogo1.gif"" width=""270"" height=""129"">"
	'arr(1) = "<img src=""http://www.baidu.com/cache/global/img/gs.gif"">"
	'------------------------------------------------------------------------------------------

	Public Function Search(ByVal rule)
		Search = Search_(s_ohtml, rule)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.Search_ 方法
	'# @syntax: AB.Http.Search_ string, regex
	'# @return: Array (数组) 返回包含搜索结果字符串的数组
	'# @dowhat: 在结果字符串中按正则表达式取得循环部分字符串并存进数组中
	'#  调用此方法可以在指定的结果字符串中按正则表达式进行匹配，
	'#  把匹配到的一个或多个结果放到数组中并返回这个数组。
	'--DESC------------------------------------------------------------------------------------
	'# @param string: [String] (字符串) 指定的结果字符串
	'# @param regex: [String] (字符串) 正则表达式
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# Dim s : s = h.Get("http://www.baidu.com/index.php")
	'# Dim arr : arr = h.Search_(s, "<img[\s]+src=""[^""]*""[^>]*>")
	'# Set h = Nothing
	'# AB.Trace arr
	'上面返回结果如：
	'arr(0) = "<img src=""http://www.baidu.com/img/baidu_sylogo1.gif"" width=""270"" height=""129"">"
	'arr(1) = "<img src=""http://www.baidu.com/cache/global/img/gs.gif"">"
	'------------------------------------------------------------------------------------------

	Public Function Search_(ByVal s, ByVal rule)
		Dim matches,match,arr(),i : i = 0
		Set matches = AB.C.RegMatch(s,rule)
		ReDim arr(matches.Count-1)
		For Each match In matches
			arr(i) = match.Value
			i = i + 1
		Next
		Set matches = Nothing
		Search_ = arr
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.SubStr 方法
	'# @syntax: AB.Http.SubStr beginCode, endCode, type
	'# @return: String (字符串) 截取到的字符串
	'# @dowhat: 在结果中按开始和结束标签截取字符串
	'#  调用此方法可以把读取到远程文件源码按开始代码和结束代码进行截取，并返回从开始代码到结束代码之间的字符串。
	'--DESC------------------------------------------------------------------------------------
	'# @param beginCode: [String] (字符串) 开始代码
	'# @param endCode:   [String] (字符串) 结束代码
	'# @param type:      [Integer] (整型数字) 返回类型，类型不同则返回结果不同
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.Get("http://www.baidu.com/index.php")
	'# Dim str : str = h.SubStr("<div id=""u"">", "</div>", type)
	'# Set h = Nothing
	'# AB.C.Print str
	'# ------------------
	'# ===当 type = 1 时：
	'# <div id="u"><a href="http://www.baidu.com/gaoji/preferences.html" name="tj_setting">搜索设置</a>|<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login">登录</a><a href="https://passport.baidu.com/v2/?reg&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" target="_blank" name="tj_reg" class="reg">注册</a></div>
	'# ===当 type = 2 时：
	'# <div id="u"><a href="http://www.baidu.com/gaoji/preferences.html" name="tj_setting">搜索设置</a>|<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login">登录</a><a href="https://passport.baidu.com/v2/?reg&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" target="_blank" name="tj_reg" class="reg">注册</a>
	'# ===当 type = 3 时：
	'# <a href="http://www.baidu.com/gaoji/preferences.html" name="tj_setting">搜索设置</a>|<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login">登录</a><a href="https://passport.baidu.com/v2/?reg&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" target="_blank" name="tj_reg" class="reg">注册</a></div>
	'# ===当 type = 0 或 其他 时：
	'# <a href="http://www.baidu.com/gaoji/preferences.html" name="tj_setting">搜索设置</a>|<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login">登录</a><a href="https://passport.baidu.com/v2/?reg&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" target="_blank" name="tj_reg" class="reg">注册</a>
	'------------------------------------------------------------------------------------------

	Public Function SubStr(ByVal tagStart, ByVal tagEnd, ByVal tagSelf)
		SubStr = SubStr_(s_ohtml,tagStart,tagEnd,tagSelf)
	End Function

	Public Function SubStr_(ByVal s, ByVal tagStart, ByVal tagEnd, ByVal tagSelf)
		Dim posA, posB, first, between
		posA = instr(1,s,tagStart,1)
		If posA=0 Then SubStr_ = "源代码中不包括此开始标签" : Exit Function
		posB = instr(PosA+Len(tagStart),s,tagEnd,1)
		If posB=0 Then SubStr_ = "源代码中不包括此结束标签" : Exit Function
		Select Case tagSelf
			Case 1
				first = posA
				between = posB+len(tagEnd)-first
			Case 2
				first = posA
				between = posB-first
			Case 3
				first = posA+len(tagStart)
				between = posB+len(tagEnd)-first
			Case Else
				first = posA+len(tagStart)
				between = posB-first
		End Select
		SubStr_ = Mid(s,first,between)
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.SaveImgTo 方法
	'# @syntax: AB.Http.SaveImgTo p
	'# @return: String (字符串) 将读取的远程文件代码中含有远程图片地址保存下载并替换为本地图片地址，返回结果字符串
	'# @dowhat: 保存下载远程代码中的远程图片并替换为本地图片地址
	'#  将读取的远程代码中含有远程图片地址保存下载并替换为本地图片地址，返回结果字符串
	'--DESC------------------------------------------------------------------------------------
	'# @param p: [String] (字符串) 指定保存的目录，为空则为当前目录下
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "Http"
	'# Dim h : Set h = AB.Http.New
	'# h.Get("http://www.baidu.com/index.php")
	'# AB.C.Print h.SaveImgTo("img/")
	'# Set h = Nothing
	'------------------------------------------------------------------------------------------

	Public Function SaveImgTo(ByVal p)
		SaveImgTo = SaveImgTo_(s_ohtml,p)
	End Function

	Public Function SaveImgTo_(ByVal s, ByVal p)
		Dim a,b, i, img, ht, tmp, src
		a = AB.C.GetImg(s)
		b = AB.C.GetImgTag(s)
		If AB.C.Has(a) Then
			AB.Use "Fso"
			For i = 0 To Ubound(a)
				If SaveRandom Then
					img = AB.C.DateTime(Now,"ymmddhhiiss"&AB.C.RandStr("5:0123456789")) & Mid(a(i),InstrRev(a(i),"."))
				Else
					img = Mid(a(i),InstrRev(a(i),"/")+1)
				End If
				Set ht = AB.Http.New
				ht.Get TransPath(s_url, a(i))
				tmp = AB.Fso.SaveAs(p & img, ht.Body)
				Set ht = Nothing
				If tmp Then
					src = AB.C.RegReplace(b(i),"(<img\s[^>]*src\s*=\s*([""|']?))("&a(i)&")(\2[^>]*>)","$1"&p&img&"$4")
					s = Replace(s,b(i),src)
				End If
			Next
		End If
		SaveImgTo_ = s
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Http.AjaxAgent 方法
	'# @syntax: AB.Http.AjaxAgent()
	'# @return: String (字符串) 远程源代码
	'# @dowhat: 通过发送带aburl参数的目标地址来获取远程源代码
	'--DESC------------------------------------------------------------------------------------
	'# @param p: [String] (字符串) 指定保存的目录，为空则为当前目录下
	'--DEMO------------------------------------------------------------------------------------
	'# 'url: /test.asp?aburl=http://www.baidu.com/index.php
	'# AB.Use "Http"
	'# AB.Http.AjaxAgent()
	'------------------------------------------------------------------------------------------

	Public Sub AjaxAgent()
		AB.C.NoCache()
		Dim u, qs, qskey, qf, qfkey, m
		u = AB.C.Get("aburl")
		If AB.C.IsNul(u) Then AB.C.Put "error:Invalid URL"
		If Instr(u,"?")>0 Then
			qs = "&" & AB.C.CRight(u,"?")
			u = AB.C.Cleft(u,"?")
		End If
		If Request.QueryString()<>"" Then
			For Each qskey In Request.QueryString
				If qskey<>"aburl" Then qs = qs & "&" & qskey & "=" & Request.QueryString(qskey)
			Next
		End If
		u = u & AB.C.IfThen(AB.C.Has(qs),"?" & Mid(qs,2))
		m = Request.ServerVariables("REQUEST_METHOD")
		If m = "POST" Then
			If Request.Form()<>"" Then
				For Each qfkey In Request.Form
					qf = qf & "&" & qfkey & "=" & Request.Form(qfkey)
				Next
				Data = Mid(qf,2)
			End If
			AB.C.Put Post(u)
		Else
			AB.C.Put [Get](u)
		End If
	End Sub

	Function TransPath(ByVal u, ByVal p)
		If Left(p,7)="http://" Or Left(p,8)="https://" Then TransPath = p : Exit Function
		Dim tmp,ser, fol
		tmp = AB.C.Cleft(u,"?")
		If Left(u,7)<>"http://" And Left(u,8)<>"https://" Then
			ser = ""
		Else
			ser = AB.C.RegReplace(tmp,"^(https?://[a-zA-Z0-9-.]+)/(.+)$","$1")
		End If
		fol = Mid(tmp,1,InstrRev(tmp,"/"))
		TransPath = AB.C.IIF(Left(p,1) = "/", ser, fol) & p
	End Function

	Private Sub SetHeaderTo(ByRef o)
		Dim maps,key
		Set maps = o_rh.Maps
		For Each key In maps
			If Not isNumeric(key) Then
				o.setRequestHeader Replace(key,"_","-"), o_rh(key)
			End If
		Next
		Set maps = Nothing
	End Sub

	Private Function Serialize__(ByVal a)
		Dim tmp, i, n, v : tmp = ""
		If AB.C.IsNul(a) Then Exit Function
		If isArray(a) Then
			For i = 0 To Ubound(a)
				n = AB.C.Cleft(a(i),":")
				v = AB.C.CRight(a(i),":")
				tmp = tmp & "&" & n & "=" & Server.URLEncode(v)
			Next
			If Len(tmp)>1 Then tmp = Mid(tmp,2)
			Serialize__ = tmp
		Else
			Serialize__ = a
		End If
	End Function

	Private Function Bytes2Bstr__(ByVal s, ByVal s_charset)
		Dim temp, oStrm : Set oStrm = Server.CreateObject(AB.steamName)
		With oStrm
			.Type = 1
			.Mode = 3
			.Open
			.Write s
			.Position = 0
			.Type = 2
			.Charset = s_charset
			temp = .ReadText
			.Close
		End With
		Bytes2Bstr__ = temp
		Set oStrm = nothing
	End Function

End Class
%>